<!DOCTYPE HTML>
<html>
<head>
  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
  createHTML({ title: "PeerConnection feed to a graph with non default rate", bug: "1387454" });
  /**
   * Run a test to verify that when we use the streem with nonDefault rate to/from a PC
   * the connection fails. (PC is always on default rate).
   */

  let pc1;
  let pc2;

  const offerOptions = {
    offerToReceiveAudio: 1,
  };

  function getName(pc) {
    return (pc === pc1) ? 'pc1' : 'pc2';
  }

  function getOtherPc(pc) {
    return (pc === pc1) ? pc2 : pc1;
  }

  function onAddIceCandidateSuccess(pc) {
    ok(true, getName(pc) + ' addIceCandidate success');
  }

  function onAddIceCandidateError(pc, error) {
    ok(false, getName(pc) + ' failed to add ICE Candidate: ' + error.toString());
  }

  function onIceCandidate(pc, event, done) {
    if (!event.candidate) {
      ok(pc.iceGatheringState === 'complete', getName(pc) + " ICE gathering state has reached complete");
      done();
      return;
    }
    getOtherPc(pc).addIceCandidate(event.candidate)
    .then(() => {
        onAddIceCandidateSuccess(pc);
      },
      (err) => {
        onAddIceCandidateError(pc, err);
      });
    info(getName(pc) + ' ICE candidate: ' + event.candidate.candidate);
  }

  function onIceStateChange(pc, event) {
    if (pc) {
      info(getName(pc) + ' ICE state: ' + pc.iceConnectionState);
      info('ICE state change event: ', event);
    }
  }

  function onCreateOfferSuccess(desc) {
    info('Offer from pc1\n' + desc.sdp);
    info('pc1 setLocalDescription start');

    pc1.setLocalDescription(desc)
    .then(() => {
      onSetLocalSuccess(pc1);
    },
    onSetSessionDescriptionError);

    info('pc2 setRemoteDescription start');
    pc2.setRemoteDescription(desc).then(() => {
      onSetRemoteSuccess(pc2);
    },
    onSetSessionDescriptionError);

    info('pc2 createAnswer start');

    // Since the 'remote' side has no media stream we need
    // to pass in the right constraints in order for it to
    // accept the incoming offer of audio and video.
    pc2.createAnswer()
    .then(onCreateAnswerSuccess, onCreateSessionDescriptionError);
  }

  function onSetSessionDescriptionError(error) {
    ok(false, 'Failed to set session description: ' + error.toString());
  }

  function onSetLocalSuccess(pc) {
    ok(true, getName(pc) + ' setLocalDescription complete');
  }

  function onCreateSessionDescriptionError(error) {
    ok(false, 'Failed to create session description: ' + error.toString());
  }

  function onSetRemoteSuccess(pc) {
    ok(true, getName(pc) + ' setRemoteDescription complete');
  }

  function onCreateAnswerSuccess(desc) {
    info('Answer from pc2:\n' + desc.sdp);
    info('pc2 setLocalDescription start');
    pc2.setLocalDescription(desc).then(() => {
      onSetLocalSuccess(pc2);
    },
    onSetSessionDescriptionError);
    info('pc1 setRemoteDescription start');
    pc1.setRemoteDescription(desc).then(() => {
        onSetRemoteSuccess(pc1);
    },
    onSetSessionDescriptionError);
  }

  async function getRemoteStream(localStream) {
    info("got local stream")
    const audioTracks = localStream.getAudioTracks();

    const servers = null;

    pc1 = new RTCPeerConnection(servers);
    info('Created local peer connection object pc1');
    const iceComplete1 = new Promise((resolve, reject) => {
      pc1.onicecandidate = (e) => {
        onIceCandidate(pc1, e, resolve);
      };
    });

    pc2 = new RTCPeerConnection(servers);
    info('Created remote peer connection object pc2');
    const iceComplete2 = new Promise((resolve, reject) => {
      pc2.onicecandidate = (e) => {
        onIceCandidate(pc2, e, resolve);
      };
    });

    pc1.oniceconnectionstatechange = (e) => {
      onIceStateChange(pc1, e);
    };
    pc2.oniceconnectionstatechange = (e) => {
      onIceStateChange(pc2, e);
    };

    const remoteStreamPromise = new Promise((resolve, reject) => {
      pc2.ontrack = (e) => {
        info('pc2 received remote stream ' + e.streams[0]);
        resolve(e.streams[0]);
      };
    });

    localStream.getTracks().forEach((track) => {
      pc1.addTrack(track, localStream);
    });
    info('Added local stream to pc1');

    info('pc1 createOffer start');
    pc1.createOffer(offerOptions)
      .then(onCreateOfferSuccess,onCreateSessionDescriptionError);

    let promise_arr = await Promise.all([remoteStreamPromise, iceComplete1, iceComplete2]);
    return promise_arr[0];
  }

  runTest(async () => {
    // Local stream operates at non default rate (32000)
    const nonDefaultRate = 32000;
    const nonDefault_ctx = new AudioContext({sampleRate: nonDefaultRate});
    oscillator = nonDefault_ctx.createOscillator();
    const dest = nonDefault_ctx.createMediaStreamDestination();
    oscillator.connect(dest);
    oscillator.start();

    // Wait for remote stream
    const remoteStream = await getRemoteStream(dest.stream)
    ok(true, 'Got remote stream ' + remoteStream);

    // remoteStream now comes from PC so operates at default
    // rates. Verify that by adding to a default context
    const ac = new AudioContext;
    const source_default_rate = ac.createMediaStreamSource(remoteStream);

    // Now try to add the remoteStream on a non default context
    mustThrowWith(
      "Connect stream with graph of different sample rate",
      "NotSupportedError", () => {
        nonDefault_ctx.createMediaStreamSource(remoteStream);
      }
    );

    // Close peer connections to make sure we don't get error:
    // "logged result after SimpleTest.finish(): pc1 addIceCandidate success"
    // See Bug 1626814.
    pc1.close();
    pc2.close();
  });
</script>
</pre>
</body>
</html>
