<commit_before>/**
 * @license
 * Copyright 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

goog.provide('shaka.media.PlayRateController');

goog.require('goog.asserts');
goog.require('shaka.util.IReleasable');
goog.require('shaka.util.Timer');

/**
 * The play rate controller controls the playback rate on the media element.
 * This provides some missing functionality (e.g. negative playback rate). If
 * the playback rate on the media element can change outside of the controller,
 * the playback controller will need to be updated to stay in-sync.
 *
 * TODO: Try not to manage buffering above the browser with playbackRate=0.
 *
 * @implements {shaka.util.IReleasable}
 * @final
 */
shaka.media.PlayRateController = class {
  /**
   * @param {shaka.media.PlayRateController.Harness} harness
   */
  constructor(harness) {
    /** @private {?shaka.media.PlayRateController.Harness} */
    this.harness_ = harness;

    /** @private {boolean} */
    this.isBuffering_ = false;

    /** @private {number} */
    this.rate_ = this.harness_.getRate();

    /** @private {number} */
    this.pollRate_ = 0.25;

    /** @private {shaka.util.Timer} */
    this.timer_ = new shaka.util.Timer(() => {
      this.harness_.movePlayhead(this.rate_ * this.pollRate_);
    });
  }

  /** @override */
  release() {
    if (this.timer_) {
      this.timer_.stop();
      this.timer_ = null;
    }

    this.harness_ = null;
  }

  /**
   * Sets the buffering flag, which controls the effective playback rate.
   *
   * @param {boolean} isBuffering If true, forces playback rate to 0 internally.
   */
  setBuffering(isBuffering) {
    this.isBuffering_ = isBuffering;
    this.apply_();
  }

  /**
   * Set the playback rate. This rate will only be used as provided when the
   * player is not buffering. You should never set the rate to 0.
   *
   * @param {number} rate
   */
  set(rate) {
    goog.asserts.assert(rate != 0, 'Should never set rate of 0 explicitly!');
    this.rate_ = rate;
    this.apply_();
  }

  /**
   * Get the rate that the user will experience. This means that if we are using
   * trick play, this will report the trick play rate. If we are buffering, this
   * will report zero. If playback is occurring as normal, this will report 1.
   *
   * @return {number}
   */
  getActiveRate() {
    return this.calculateCurrentRate_();
  }

  /**
   * Reapply the effects of |this.rate_| and |this.active_| to the media
   * element. This will only update the rate via the harness if the desired rate
   * has changed.
   *
   * @private
   */
  apply_() {
    // Always stop the timer. We may not start it again.
    this.timer_.stop();

    /** @type {number} */
    const rate = this.calculateCurrentRate_();

    if (rate >= 0) {
      this.applyRate_(rate);
      return;
    }

    // When moving backwards, set the playback rate to 0 so that we can manually
    // seek backwards with out fighting the playhead.<commit_msg>Fall back to fast forward by seeking on large rate values.<commit_after>/**
 * @license
 * Copyright 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

goog.provide('shaka.media.PlayRateController');

goog.require('goog.asserts');
goog.require('shaka.util.IReleasable');
goog.require('shaka.util.Timer');

/**
 * The play rate controller controls the playback rate on the media element.
 * This provides some missing functionality (e.g. negative playback rate). If
 * the playback rate on the media element can change outside of the controller,
 * the playback controller will need to be updated to stay in-sync.
 *
 * TODO: Try not to manage buffering above the browser with playbackRate=0.
 *
 * @implements {shaka.util.IReleasable}
 * @final
 */
shaka.media.PlayRateController = class {
  /**
   * @param {shaka.media.PlayRateController.Harness} harness
   */
  constructor(harness) {
    /** @private {?shaka.media.PlayRateController.Harness} */
    this.harness_ = harness;

    /** @private {boolean} */
    this.isBuffering_ = false;

    /** @private {number} */
    this.rate_ = this.harness_.getRate();

    /** @private {number} */
    this.pollRate_ = 0.25;

    /** @private {shaka.util.Timer} */
    this.timer_ = new shaka.util.Timer(() => {
      this.harness_.movePlayhead(this.rate_ * this.pollRate_);
    });
  }

  /** @override */
  release() {
    if (this.timer_) {
      this.timer_.stop();
      this.timer_ = null;
    }

    this.harness_ = null;
  }

  /**
   * Sets the buffering flag, which controls the effective playback rate.
   *
   * @param {boolean} isBuffering If true, forces playback rate to 0 internally.
   */
  setBuffering(isBuffering) {
    this.isBuffering_ = isBuffering;
    this.apply_();
  }

  /**
   * Set the playback rate. This rate will only be used as provided when the
   * player is not buffering. You should never set the rate to 0.
   *
   * @param {number} rate
   */
  set(rate) {
    goog.asserts.assert(rate != 0, 'Should never set rate of 0 explicitly!');
    this.rate_ = rate;
    this.apply_();
  }

  /**
   * Get the rate that the user will experience. This means that if we are using
   * trick play, this will report the trick play rate. If we are buffering, this
   * will report zero. If playback is occurring as normal, this will report 1.
   *
   * @return {number}
   */
  getActiveRate() {
    return this.calculateCurrentRate_();
  }

  /**
   * Reapply the effects of |this.rate_| and |this.active_| to the media
   * element. This will only update the rate via the harness if the desired rate
   * has changed.
   *
   * @private
   */
  apply_() {
    // Always stop the timer. We may not start it again.
    this.timer_.stop();

    /** @type {number} */
    const rate = this.calculateCurrentRate_();

    if (rate >= 0) {
      try {
        this.applyRate_(rate);
        return;
      } catch (e) {
        // Fall through to the next clause.
        //
        // Fast forward is accomplished through setting video.playbackRate.
        // If the play rate value is not supported by the browser (too big),
        // the browsers will throw.
        // Use this as a cue to fall back to fast forward through repeated
        // seeking, which is what we do for rewind as well.
      }
    }

    // When moving backwards or forwards in large steps,
    // set the playback rate to 0 so that we can manually
    // seek backwards with out fighting the playhead.
{'fraction_non_alphanumeric': 0.1097986577181208, 'fraction_numerical': 0.005100671140939597, 'mean_word_length': 2.801530612244898, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '226232', 'n_tokens_mistral': 2250, 'n_tokens_neox': 2152, 'n_words': 810}